home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / src / fountain.c < prev    next >
C/C++ Source or Header  |  1993-01-16  |  14KB  |  538 lines

  1. /*    SCCS Id: @(#)fountain.c    3.1    92/12/19    */
  2. /*    Copyright Scott R. Turner, srt@ucla, 10/27/86 */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /* Code for drinking from fountains. */
  6.  
  7. #include "hack.h"
  8.  
  9. static void NDECL(dowatersnakes);
  10. static void NDECL(dowaterdemon);
  11. static void NDECL(dowaternymph);
  12. STATIC_PTR void FDECL(gush, (int,int,genericptr_t));
  13. static void NDECL(dofindgem);
  14.  
  15. static void
  16. dowatersnakes() /* Fountain of snakes! */
  17. {
  18.     register int num = rn1(5,2);
  19.     struct monst *mtmp;
  20.  
  21.     if (!(mons[PM_WATER_MOCCASIN].geno & (G_GENOD | G_EXTINCT))) {
  22.     if (!Blind)
  23.         pline("An endless stream of %s pours forth!",
  24.           Hallucination ? makeplural(rndmonnam()) : "snakes");
  25.     else
  26.         You("hear something hissing!");
  27.     while(num-- > 0)
  28.         if((mtmp = makemon(&mons[PM_WATER_MOCCASIN],u.ux,u.uy)) &&
  29.            t_at(mtmp->mx, mtmp->my))
  30.         (void) mintrap(mtmp);
  31.     } else
  32.     pline("The fountain bubbles furiously for a moment, then calms.");
  33. }
  34.  
  35. static
  36. void
  37. dowaterdemon() /* Water demon */
  38. {
  39.     register struct monst *mtmp;
  40.  
  41.     if(mons[PM_WATER_DEMON].geno & (G_GENOD | G_EXTINCT)) return;
  42.     if((mtmp = makemon(&mons[PM_WATER_DEMON],u.ux,u.uy))) {
  43.         if (!Blind)
  44.         You("have unleashed %s!", a_monnam(mtmp));
  45.         else
  46.         You("feel the presence of evil.");
  47.  
  48.     /* Give those on low levels a (slightly) better chance of survival */
  49.         if ( rnd(100) > (80 + level_difficulty())) {
  50.         pline("Grateful for %s release, %s grants you a wish!",
  51.             Blind ? "its" : "his", Blind ? "it" : "he" );
  52.         makewish();
  53.         mongone(mtmp);
  54.         } else if (t_at(mtmp->mx, mtmp->my))
  55.         (void) mintrap(mtmp);
  56.     }
  57. }
  58.  
  59. static void
  60. dowaternymph() /* Water Nymph */
  61. {
  62.     register struct monst *mtmp;
  63.  
  64.     if(mons[PM_WATER_NYMPH].geno & (G_GENOD | G_EXTINCT)) return;
  65.     if((mtmp = makemon(&mons[PM_WATER_NYMPH],u.ux,u.uy))) {
  66.         if (!Blind)
  67.            You("have attracted %s!", a_monnam(mtmp));
  68.         else
  69.            You("hear a seductive voice.");
  70.         mtmp->msleep = 0;
  71.         if (t_at(mtmp->mx, mtmp->my))
  72.             (void) mintrap(mtmp);
  73.     } else
  74.         if (!Blind)
  75.            pline("A large bubble rises to the surface and pops.");
  76.         else
  77.            You("hear a loud pop.");
  78. }
  79.  
  80. void
  81. dogushforth(drinking) /* Gushing forth along LOS from (u.ux, u.uy) */
  82. int drinking;
  83. {
  84.     int madepool = 0;
  85.  
  86.     do_clear_area(u.ux, u.uy, 7, gush, (genericptr_t)&madepool);
  87.     if (!madepool)
  88.         if (drinking)
  89.         Your("thirst is quenched.");
  90.         else
  91.         pline("Water sprays all over you.");
  92. }
  93.  
  94. STATIC_PTR void
  95. gush(x, y, poolcnt)
  96. int x, y;
  97. genericptr_t poolcnt;
  98. {
  99.     register struct monst *mtmp;
  100.  
  101.     if (((x+y)%2) || (x == u.ux && y == u.uy) ||
  102.         (rn2(1 + distmin(u.ux, u.uy, x, y)))  ||
  103.         (levl[x][y].typ != ROOM) || t_at(x,y) ||
  104.         (sobj_at(BOULDER, x, y)) || nexttodoor(x, y))
  105.         return;
  106.  
  107.     if (!((*(int *)poolcnt)++))
  108.         pline("Water gushes forth from the overflowing fountain!");
  109.  
  110.     /* Put a pool at x, y */
  111.  
  112.     levl[x][y].typ = POOL;
  113.  
  114.     if ((mtmp = m_at(x, y)) != 0)
  115.         (void) minwater(mtmp);
  116.     else
  117.         newsym(x,y);
  118. }
  119.  
  120. static void
  121. dofindgem() /* Find a gem in the sparkling waters. */
  122. {
  123.     if (!Blind) You("spot a gem in the sparkling waters!");
  124.     (void) mksobj_at(rnd_class(DILITHIUM_CRYSTAL, LUCKSTONE-1),
  125.                         u.ux, u.uy, FALSE);
  126.     levl[u.ux][u.uy].looted |= F_LOOTED;
  127.     newsym(u.ux, u.uy);
  128.     exercise(A_WIS, TRUE);            /* a discovery! */
  129. }
  130.  
  131. void
  132. dryup(x,y)
  133. xchar x, y;
  134. {
  135.     boolean isyou = (x == u.ux && y == u.uy);
  136.  
  137.     if (IS_FOUNTAIN(levl[x][y].typ) &&
  138.         (!rn2(3) || (levl[x][y].looted & F_WARNED))) {
  139.         s_level *slev = Is_special(&u.uz);
  140.         if(isyou && slev && slev->flags.town &&
  141.            !(levl[x][y].looted & F_WARNED)) {
  142.             struct monst *mtmp;
  143.             levl[x][y].looted |= F_WARNED;
  144.             /* Warn about future fountain use. */
  145.             for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
  146.                 if((mtmp->data == &mons[PM_WATCHMAN] ||
  147.                 mtmp->data == &mons[PM_WATCH_CAPTAIN]) &&
  148.                    couldsee(mtmp->mx, mtmp->my) &&
  149.                    mtmp->mpeaceful) {
  150.                 pline("%s yells:", Amonnam(mtmp));
  151.                 verbalize("Hey, stop using that fountain!");
  152.                 break;
  153.                 }
  154.             }
  155.             /* You can see or hear this effect */
  156.             if(!mtmp) pline("The waterflow reduces to a trickle.");
  157.             return;
  158.         }
  159. #ifdef WIZARD
  160.         if (isyou && wizard) {
  161.             if (yn("Dry up fountain?") == 'n')
  162.                 return;
  163.         }
  164. #endif
  165.         if (cansee(x,y)) pline("The fountain dries up!");
  166.         levl[x][y].typ = ROOM;
  167.         levl[x][y].looted = 0;
  168.         levl[x][y].blessedftn = 0;
  169.         /* The location is seen if the hero/monster is invisible */
  170.         /* or felt if the hero is blind.             */
  171.         newsym(x, y);
  172.         level.flags.nfountains--;
  173.         if(isyou && slev && slev->flags.town)
  174.             (void) angry_guards(FALSE);
  175.     }
  176. }
  177.  
  178. void
  179. drinkfountain()
  180. {
  181.     /* What happens when you drink from a fountain? */
  182.     register boolean mgkftn = (levl[u.ux][u.uy].blessedftn == 1);
  183.     register int fate = rnd(30);
  184.  
  185.     if (Levitation) {
  186.         You("are floating high above the fountain.");
  187.         return;
  188.     }
  189.  
  190.     if (mgkftn && u.uluck >= 0 && fate >= 10) {
  191.         int i, ii, littleluck = (u.uluck < 4);
  192.  
  193.         pline("Wow!  This makes you feel great!");
  194.         /* blessed restore ability */
  195.         for (ii = 0; ii < A_MAX; ii++)
  196.             if (ABASE(ii) < AMAX(ii)) {
  197.             ABASE(ii) = AMAX(ii);
  198.             flags.botl = 1;
  199.             }
  200.         /* gain ability, blessed if "natural" luck is high */
  201.         i = rn2(A_MAX);        /* start at a random attribute */
  202.         for (ii = 0; ii < A_MAX; ii++) {
  203.             if (adjattrib(i, 1, littleluck ? -1 : 0) && littleluck)
  204.             break;
  205.             if (++i >= A_MAX) i = 0;
  206.         }
  207.         display_nhwindow(WIN_MESSAGE, FALSE);
  208.         pline("A wisp of vapor escapes the fountain....");
  209.         exercise(A_WIS, TRUE);
  210.         levl[u.ux][u.uy].blessedftn = 0;
  211.         return;
  212.     }
  213.  
  214.     if (fate < 10) {
  215.         pline("The cool draught refreshes you.");
  216.         u.uhunger += rnd(10); /* don't choke on water */
  217.         newuhs(FALSE);
  218.         if(mgkftn) return;
  219.     } else {
  220.         switch (fate) {
  221.  
  222.         case 19: /* Self-knowledge */
  223.  
  224.             You("feel self-knowledgeable....");
  225.             display_nhwindow(WIN_MESSAGE, FALSE);
  226.             enlightenment(FALSE);
  227.             exercise(A_WIS, TRUE);
  228.             pline("The feeling subsides.");
  229.             break;
  230.  
  231.         case 20: /* Foul water */
  232.  
  233.             pline("The water is foul!  You gag and vomit.");
  234.             morehungry(rn1(20, 11));
  235.             vomit();
  236.             break;
  237.  
  238.         case 21: /* Poisonous */
  239.  
  240.             pline("The water is contaminated!");
  241.             if (Poison_resistance) {
  242. #ifdef TUTTI_FRUTTI
  243.        pline("Perhaps it is runoff from the nearby %s farm.", pl_fruit);
  244. #else
  245.        pline("Perhaps it is runoff from the nearby orange farm.");
  246. #endif
  247.                losehp(rnd(4),"unrefrigerated sip of juice",
  248.                 KILLED_BY_AN);
  249.                break;
  250.             }
  251.             losestr(rn1(4,3));
  252.             losehp(rnd(10),"contaminated water", KILLED_BY);
  253.             exercise(A_CON, FALSE);
  254.             break;
  255.  
  256.         case 22: /* Fountain of snakes! */
  257.  
  258.             dowatersnakes();
  259.             break;
  260.  
  261.         case 23: /* Water demon */
  262.             dowaterdemon();
  263.             break;
  264.  
  265.         case 24: /* Curse an item */ {
  266.             register struct obj *obj;
  267.  
  268.             pline("This water's no good!");
  269.             morehungry(rn1(20, 11));
  270.             exercise(A_CON, FALSE);
  271.             for(obj = invent; obj ; obj = obj->nobj)
  272.                 if (!rn2(5))    curse(obj);
  273.             break;
  274.             }
  275.  
  276.         case 25: /* See invisible */
  277.  
  278.             You("see an image of someone stalking you.");
  279.             pline("But it disappears.");
  280.             HSee_invisible |= FROMOUTSIDE;
  281.             newsym(u.ux,u.uy);
  282.             exercise(A_WIS, TRUE);
  283.             break;
  284.  
  285.         case 26: /* See Monsters */
  286.  
  287.             (void) monster_detect((struct obj *)0, 0);
  288.             exercise(A_WIS, TRUE);
  289.             break;
  290.  
  291.         case 27: /* Find a gem in the sparkling waters. */
  292.  
  293.             if (!levl[u.ux][u.uy].looted) {
  294.                 dofindgem();
  295.                 break;
  296.             }
  297.  
  298.         case 28: /* Water Nymph */
  299.  
  300.             dowaternymph();
  301.             break;
  302.  
  303.         case 29: /* Scare */ {
  304.             register struct monst *mtmp;
  305.  
  306.             pline("This water gives you bad breath!");
  307.             for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  308.                 mtmp->mflee = 1;
  309.             }
  310.             break;
  311.  
  312.         case 30: /* Gushing forth in this room */
  313.  
  314.             dogushforth(TRUE);
  315.             break;
  316.  
  317.         default:
  318.  
  319.             pline("This tepid water is tasteless.");
  320.             break;
  321.         }
  322.     }
  323.     dryup(u.ux, u.uy);
  324. }
  325.  
  326. void
  327. dipfountain(obj)
  328. register struct obj *obj;
  329. {
  330.     if (Levitation) {
  331.         You("are floating high above the fountain.");
  332.         return;
  333.     }
  334.  
  335.     /* Don't grant Excalibur when there's more than one object.  */
  336.     /* (quantity could be > 1 if merged daggers got polymorphed) */
  337.     if (obj->otyp == LONG_SWORD && obj->quan == 1L
  338.         && u.ulevel >= 5 && !rn2(6)
  339.         && !obj->oartifact
  340.         && !exist_artifact(LONG_SWORD, artiname(ART_EXCALIBUR))) {
  341.         if (u.ualign.type != A_LAWFUL) {
  342.             /* Ha!  Trying to cheat her. */
  343.             pline("A freezing mist rises from the water and envelopes the sword.");
  344.             pline("The fountain disappears!");
  345.             curse(obj);
  346.             if (obj->spe > -6 && !rn2(3)) obj->spe--;
  347.             obj->oerodeproof = FALSE;
  348.             exercise(A_WIS, FALSE);
  349.         } else {
  350.             /* The lady of the lake acts! - Eric Backus */
  351.             /* Be *REAL* nice */
  352.       pline("From the murky depths, a hand reaches up to bless the sword.");
  353.             pline("As the hand retreats, the fountain disappears!");
  354.             obj = oname(obj, artiname(ART_EXCALIBUR), 1);
  355.             bless(obj);
  356.             obj->oeroded = 0;
  357.             obj->oerodeproof = TRUE;
  358.             exercise(A_WIS, TRUE);
  359.         }
  360.         levl[u.ux][u.uy].typ = ROOM;
  361.         levl[u.ux][u.uy].looted = 0;
  362.         if(Invisible) newsym(u.ux, u.uy);
  363.         level.flags.nfountains--;
  364.         return;
  365.     } else (void) get_wet(obj);
  366.  
  367.     switch (rnd(30)) {
  368.         case 16: /* Curse the item */
  369.             curse(obj);
  370.             break;
  371.         case 17:
  372.         case 18:
  373.         case 19:
  374.         case 20: /* Uncurse the item */
  375.             if(obj->cursed) {
  376.                 if (!Blind)
  377.                 pline("The water glows for a moment.");
  378.                 uncurse(obj);
  379.             } else {
  380.                 pline("A feeling of loss comes over you.");
  381.             }
  382.             break;
  383.         case 21: /* Water Demon */
  384.             dowaterdemon();
  385.             break;
  386.         case 22: /* Water Nymph */
  387.             dowaternymph();
  388.             break;
  389.         case 23: /* an Endless Stream of Snakes */
  390.             dowatersnakes();
  391.             break;
  392.         case 24: /* Find a gem */
  393.             dofindgem();
  394.             break;
  395.         case 25: /* Water gushes forth */
  396.             dogushforth(FALSE);
  397.             break;
  398.         case 26: /* Strange feeling */
  399.             pline("A strange tingling runs up your %s.",
  400.                             body_part(ARM));
  401.             break;
  402.         case 27: /* Strange feeling */
  403.             You("feel a sudden chill.");
  404.             break;
  405.         case 28: /* Strange feeling */
  406.             pline("An urge to take a bath overwhelms you.");
  407.             if (u.ugold > 10) {
  408.                 u.ugold -= somegold() / 10;
  409.                 You("lost some of your gold in the fountain!");
  410.                 levl[u.ux][u.uy].looted &= ~F_LOOTED;
  411.                 exercise(A_WIS, FALSE);
  412.             }
  413.             break;
  414.         case 29: /* You see coins */
  415.  
  416.         /* We make fountains have more coins the closer you are to the
  417.          * surface.  After all, there will have been more people going
  418.          * by.    Just like a shopping mall!  Chris Woodbury  */
  419.  
  420.             mkgold((long)
  421.             (rnd((dunlevs_in_dungeon(&u.uz)-dunlev(&u.uz)+1)*2)+5),
  422.             u.ux, u.uy);
  423.             if (!Blind)
  424.         pline("Far below you, you see coins glistening in the water.");
  425.             exercise(A_WIS, TRUE);
  426.             break;
  427.     }
  428.     dryup(u.ux, u.uy);
  429. }
  430.  
  431. #ifdef SINKS
  432. void
  433. breaksink(x,y)
  434. int x, y;
  435. {
  436.     if(cansee(x,y) || (x == u.ux && y == u.uy))
  437.     pline("The pipes break!  Water spurts out!");
  438.     level.flags.nsinks--;
  439.     levl[x][y].doormask = 0;
  440.     levl[x][y].typ = FOUNTAIN;
  441.     level.flags.nfountains++;
  442.     newsym(x,y);
  443. }
  444.  
  445. void
  446. drinksink()
  447. {
  448.     if (Levitation) {
  449.         You("are floating high above the sink.");
  450.         return;
  451.     }
  452.     switch(rn2(20)) {
  453.         static struct obj NEARDATA *otmp;
  454.         case 0: You("take a sip of very cold water.");
  455.             break;
  456.         case 1: You("take a sip of very warm water.");
  457.             break;
  458.         case 2: You("take a sip of scalding hot water.");
  459.             if (Fire_resistance)
  460.                 pline("It seems quite tasty.");
  461.             else losehp(rnd(6), "sipping boiling water", KILLED_BY);
  462.             break;
  463.         case 3: if (mons[PM_SEWER_RAT].geno & (G_GENOD | G_EXTINCT))
  464.                 pline("The sink seems quite dirty.");
  465.             else {
  466.                 static struct monst NEARDATA *mtmp;
  467.  
  468.                 mtmp = makemon(&mons[PM_SEWER_RAT], u.ux, u.uy);
  469.                 pline("Eek!  There's %s in the sink!",
  470.                     Blind ? "something squirmy" :
  471.                     a_monnam(mtmp));
  472.             }
  473.             break;
  474.         case 4: do {
  475.                 otmp = mkobj(POTION_CLASS,FALSE);
  476.                 if (otmp->otyp == POT_WATER) {
  477.                     obfree(otmp, (struct obj *)0);
  478.                     otmp = (struct obj *) 0;
  479.                 }
  480.             } while(!otmp);
  481.             otmp->cursed = otmp->blessed = 0;
  482.             if (Blind)
  483.                 pline("The sink emits some odd liquid.");
  484.             else
  485.                 pline("The sink emits a stream of %s water.",
  486.                     Hallucination ? hcolor() :
  487.                     OBJ_DESCR(objects[otmp->otyp]));
  488.             otmp->dknown = !(Blind || Hallucination);
  489.             otmp->quan++; /* Avoid panic upon useup() */
  490.             otmp->corpsenm = 1; /* kludge for docall() */
  491.             (void) dopotion(otmp);
  492.             obfree(otmp, (struct obj *)0);
  493.             break;
  494.         case 5: if (!(levl[u.ux][u.uy].looted & S_LRING)) {
  495.                 You("find a ring in the sink!");
  496.                 (void) mkobj_at(RING_CLASS, u.ux, u.uy, TRUE);
  497.                 levl[u.ux][u.uy].looted |= S_LRING;
  498.                 exercise(A_WIS, TRUE);
  499.             } else pline("Some dirty water backs up in the drain.");
  500.             break;
  501.         case 6: breaksink(u.ux,u.uy);
  502.             break;
  503.         case 7: pline("The water moves as though of its own will!");
  504.             if ((mons[PM_WATER_ELEMENTAL].geno & (G_GENOD | G_EXTINCT))
  505.                 || !makemon(&mons[PM_WATER_ELEMENTAL], u.ux, u.uy))
  506.                 pline("But it quiets down.");
  507.             break;
  508.         case 8: pline("Yuk, this water tastes awful.");
  509.             more_experienced(1,0);
  510.             newexplevel();
  511.             break;
  512.         case 9: pline("Gaggg... this tastes like sewage!  You vomit.");
  513.             morehungry(rn1(30-ACURR(A_CON), 11));
  514.             vomit();
  515.             break;
  516. #ifdef POLYSELF
  517.         case 10: pline("This water contains toxic wastes!");
  518.             You("undergo a freakish metamorphosis!");
  519.             polyself();
  520.             break;
  521. #endif
  522.         /* more odd messages --JJB */
  523.         case 11: You("hear clanking from the pipes....");
  524.             break;
  525.         case 12: You("hear snatches of song from among the sewers....");
  526.             break;
  527.         case 19: if (Hallucination) {
  528.            pline("From the murky drain, a hand reaches up... --oops--");
  529.                 break;
  530.             }
  531.         default: You("take a sip of %s water.",
  532.             rn2(3) ? (rn2(2) ? "cold" : "warm") : "hot");
  533.     }
  534. }
  535. #endif /* SINKS */
  536.  
  537. /*fountain.c*/
  538.